package ch.ethz.fcl.metrobuzz.data.roadnetwork.hierarchy;

import java.util.ArrayList;

import ch.ethz.fcl.metrobuzz.data.scene.MBScene;
import ch.ethz.fcl.metrobuzz.data.scene.basemap.Edge;
import ch.ethz.fcl.metrobuzz.data.scene.basemap.Node;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Point2D;

public class Arc{
	private int index;
	private MBScene scene;
	ArrayList<Edge> edges;

	private float length;
	private Point2D mid = null;

	private ArrayList<Integer> postArcIndex;
	private ArrayList<Integer> preArcIndex;

	private ArrayList<Node> nodes;

	public Arc(MBScene scene, int id) {
		this.index = id;
		this.scene = scene;
		edges = new ArrayList<Edge>();

		postArcIndex = new ArrayList<Integer>();
		preArcIndex = new ArrayList<Integer>();
	}

	public void addEdge(Edge edge, int index) {
		if (!edges.contains(edge))
			edges.add(index, edge);
	}

	/**
	 * initialize all attributes for this arc
	 */
	public void init() {
		// initialize length
		for (int i = 0; i < size(); i++)
			length += edges.get(i).length();
		int index = 0;
		float dist = 0;
		while (index < size() - 1
				&& dist + getEdges().get(index).length() < length / 2) {
			dist += getEdges().get(index).length();
			index++;
		}
		Edge e = getEdges().get(index);
		mid = e.getStartNode().toPoint()
				.getPointAt(e.getDir(), length / 2 - dist);
	}

	public ArrayList<Edge> getEdges() {
		return edges;
	}

	public int size() {
		return edges.size();
	}

	public int getIndex() {
		return index;
	}

	public Edge getStartEdge() {
		return edges.get(0);
	}

	public Edge getEndEdge() {
		return edges.get(size() - 1);
	}

	public Node getStartNode() {
		return scene.getNode(edges.get(0).getStartNodeIndex());
	}

	public Node getEndNode() {
		return scene.getNode(edges.get(size() - 1).getEndNodeIndex());
	}

	public float getLength() {
		return length;
	}

	public Point2D getMiddlePoint() {
		return mid;
	}

	public float distance(float x, float y) {
		return (float) Math.sqrt(Math.pow(x - mid.getX(), 2)
				+ Math.pow(y - mid.getY(), 2));

	}

	public void addPostArcIndex(int index) {
		postArcIndex.add(index);
	}

	public ArrayList<Integer> getPostArcIndex() {
		return postArcIndex;
	}

	public void addPreArcIndex(int index) {
		preArcIndex.add(index);
	}

	public ArrayList<Integer> getPreArcIndex() {
		return preArcIndex;
	}

	public ArrayList<Node> getNodes() {
		if (nodes == null) {
			nodes = new ArrayList<Node>();

			for (Edge edge : edges)
				nodes.add(edge.getStartNode());
			nodes.add(edges.get(size() - 1).getEndNode());
		}
		return nodes;
	}
}
